package com.gvtv.main.execute;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.gvtv.main.job.JobInfo;
import com.gvtv.main.job.ParamInfo;

public class ExecuteJob {

	public enum ExecuteJobState {
		SUCCESS("success"), WAITING("waiting"), RUNNING("running"), READY("ready"), 
		READY_RUNNING("ready_running"), FAILED("failed"), DEPENDENT_FAILED("dependent_failed");
		
		private String name;
		ExecuteJobState(String name){
			this.name = name;
		}
		public static ExecuteJobState parser(String name){
			for(ExecuteJobState jobState : ExecuteJobState.values()){
				if(jobState.name.equalsIgnoreCase(name)){
					return jobState;
				}
			}
			return null;
		}
		public String toString() {
			return name;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
		
	};
	
	private String id;
	private String schedulId;
	private JobInfo jobInfo;
	private ExecuteJobState jobState;
	private List<ExecuteJob> dependJobs;
	private Date submitTime;
	private Date startTime;
	private Date endTime;
	private String mapReduceJobName;
	
	public ExecuteJob(String schedulId, JobInfo jobInfo){
		this.id = jobInfo.getId();
		this.schedulId = schedulId;
		this.jobInfo = jobInfo;
		this.jobState = ExecuteJobState.WAITING;
		this.dependJobs = null;
	}
	
	public String getJobName(){
		return this.jobInfo.getName();
	}
	
	public String getJobType(){
		return this.jobInfo.getType();
	}
	
	public List<ParamInfo> getParams() {
		return this.jobInfo.getParams();
	}
	
	public void addDependJob(ExecuteJob dependJob){
		if(this.dependJobs==null){
			dependJobs = new ArrayList<ExecuteJob>();
		}
		boolean isExists = false;
		for (ExecuteJob executeJob : dependJobs) {
			if(dependJob.getId().equals(executeJob.getId())){
				isExists = true;
				break;
			}
		}
		if(!isExists){
			dependJobs.add(dependJob);
		}
	}
	
	public void addDependJob(List<ExecuteJob> dependJobs){
		for (ExecuteJob executeJob : dependJobs) {
			this.addDependJob(executeJob);
		}
	}
	
	public ExecuteJobState checkJobState() {
		if (this.jobState == ExecuteJobState.READY_RUNNING || this.jobState != ExecuteJobState.WAITING) {
			return jobState;
		}
		if (this.dependJobs == null || this.dependJobs.size() == 0) {
			if (this.jobState == ExecuteJobState.WAITING) {
				this.jobState = ExecuteJobState.READY;
			}
			return this.jobState;
		}
		ExecuteJob preJob = null;
		for (int i = 0, n = dependJobs.size(); i < n; i++) {
			preJob = dependJobs.get(i);
			ExecuteJobState s = preJob.checkJobState();
			// JobState s = preJobNode.getJobState();
			if (s == ExecuteJobState.WAITING || s == ExecuteJobState.READY || s== ExecuteJobState.READY_RUNNING || s == ExecuteJobState.RUNNING) {
				break;
			}
			if (s == ExecuteJobState.FAILED || s == ExecuteJobState.DEPENDENT_FAILED) {
				this.jobState = ExecuteJobState.DEPENDENT_FAILED;
				break;
			}
			if (i == n - 1) {
				this.jobState = ExecuteJobState.READY;
			}
		}
		return this.jobState;
	}
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getSchedulId() {
		return schedulId;
	}

	public void setSchedulId(String schedulId) {
		this.schedulId = schedulId;
	}

	public JobInfo getJobInfo() {
		return jobInfo;
	}

	public void setJobInfo(JobInfo jobInfo) {
		this.jobInfo = jobInfo;
	}

	public ExecuteJobState getJobState() {
		return jobState;
	}

	public void setJobState(ExecuteJobState jobState) {
		this.jobState = jobState;
	}

	public Date getSubmitTime() {
		return submitTime;
	}

	public void setSubmitTime(Date submitTime) {
		this.submitTime = submitTime;
	}

	public Date getStartTime() {
		return startTime;
	}

	public void setStartTime(Date startTime) {
		this.startTime = startTime;
	}

	public Date getEndTime() {
		return endTime;
	}

	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}

	public List<ExecuteJob> getDependJobs() {
		return dependJobs;
	}

	public void setDependJobs(List<ExecuteJob> dependJobs) {
		this.dependJobs = dependJobs;
	}

	public String getMapReduceJobName() {
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		for (ParamInfo paramInfo : list) {
			if("-D".equalsIgnoreCase(paramInfo.getType())){
				String[] strs = paramInfo.getValue().split("=");
				if("mapreduce.job.name".equals(strs[0].trim())&&strs.length>1){
					mapReduceJobName = strs[1];
					break;
				}
			}
		}
		return mapReduceJobName;
	}

	public String getJar(){
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		for (ParamInfo paramInfo : list) {
			if("jar".equalsIgnoreCase(paramInfo.getType())){
				return paramInfo.getValue();
			}
		}
		return null;
	}
	
	public String getLibjars(){
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		for (ParamInfo paramInfo : list) {
			if("-libjars".equalsIgnoreCase(paramInfo.getType())){
				return paramInfo.getValue();
			}
		}
		return null;
	}
	
	public List<String> getDs(){
		return this.getParamsByType("-D");
	}
	
	public List<String> getArgs(){
		return this.getParamsByType("arg");
	}
	
	public List<String> getHiveSets(){
		return this.getParamsByType("set");
	}
	
	public List<String> getMRRunArgs(){
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		List<String> rel = new ArrayList<String>();
		for (ParamInfo paramInfo : list) {
			if(paramInfo.getType().startsWith("-")){
				rel.add(paramInfo.getType());
				rel.add(paramInfo.getValue());
			}else {
				rel.add(paramInfo.getValue());
			}
		}
		return rel;
	}
	
	public String getScript(){
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		StringBuffer buffer = new StringBuffer();
		for (ParamInfo paramInfo : list) {
			if("script".equalsIgnoreCase(paramInfo.getType())){
				buffer.append(paramInfo.getValue());
			}
		}
		return buffer.toString();
	}
	
	public List<String> getParamsByType(String type){
		if(StringUtils.isBlank(type)){
			return null;
		}
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		List<String> rel = new ArrayList<String>();
		for (ParamInfo paramInfo : list) {
			if(type.equalsIgnoreCase(paramInfo.getType())){
				rel.add(paramInfo.getValue());
			}
		}
		return rel;
	}
	public String getParamValue(String name){
		List<ParamInfo> list = getParams();
		if(list==null || list.size()==0){
			return null;
		}
		for (ParamInfo paramInfo : list) {
			if(name.equalsIgnoreCase(paramInfo.getName())){
				return paramInfo.getValue();
			}
		}
		return null;
	}
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("ExecuteJob [id=").append(id).append(", jobInfo=").append(jobInfo)
		.append(", jobState=").append(jobState).append(", dependJobs=[");
		if(dependJobs==null){
			buffer.append("null]");
		}else {
			for (ExecuteJob executeJob : dependJobs) {
				buffer.append(executeJob.getId()).append(",");
			}
		}
		buffer.append("]");
		return buffer.toString();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ExecuteJob other = (ExecuteJob) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
}
